/*
Copyright 2011, CSE Shareware Foundation
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, 
   this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, 
   this list of conditions and the following disclaimer in the documentation 
   and/or other materials provided with the distribution.
 * Neither the name of CSE Shareware Foundation nor the names of its contributors 
   may be used to endorse or promote products derived from this software without 
   specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef _CSETYPES_H_CSEAPI_
#define _CSETYPES_H_CSEAPI_

#include <stdlib.h>
#include <stdarg.h>
#include <assert.h>

#ifdef _WIN32
  #undef __BIT64SYS__

  #ifndef __WINDOWS__
    #define __WINDOWS__
  #endif
#endif

#ifdef _WIN64
  #ifndef _WIN32
    #define _WIN32   // define it for compatibility reasons
  #endif

  #ifndef __BIT64SYS__
    #define __BIT64SYS__
  #endif

  #ifndef __WINDOWS__
    #define __WINDOWS__
  #endif
#endif

#if defined(_UNICODE)
  #undef CSE_USE_UNICODE
  #define CSE_USE_UNICODE          1
#else
  #ifndef CSE_USE_UNICODE
    #define CSE_USE_UNICODE        0
  #endif
#endif

#if CSE_USE_UNICODE
  #ifndef _UNICODE
    #define _UNICODE
  #endif
#endif

// CSE API version and feature: V2.2.0.0
#define CSE_API_VERSION            0x02020000
#if !defined(_UNICODE)
  #define CSE_FEATURE_FLAG         0x00000000     // SBCS
#else
  #define CSE_FEATURE_FLAG         0x00000001     // unicode
#endif

#ifndef NULL
  #ifdef  __cplusplus
    #define NULL                   0L
  #else
    #define NULL                   ((void *)0)
  #endif
#endif

#ifndef true
  #define true                     1
#endif
#ifndef false
  #define false                    0
#endif

#if defined(__WINDOWS__)
  #if defined(_MSC_VER) && _MSC_VER >= 1200 // support VC6 and later version
    #define __VISUALC__            _MSC_VER
  #else
    #undef __VISUALC__
  #endif
#endif

#if defined(__VISUALC__)
  // rename usage of "struct tm" that declared in time.h
  #define struct_tm struct tm
  
  #ifndef _WCHAR_T_DEFINED
    typedef unsigned short         wchar_t;
    #define _WCHAR_T_DEFINED
  #endif

  #ifndef _VA_LIST_DEFINED
    typedef char*                  va_list;
    #define _VA_LIST_DEFINED
  #endif

  typedef char                     TChar;
  typedef wchar_t                  TWchar;

  typedef char                     TInt8;
  typedef unsigned char            TUint8;
  typedef short                    TInt16;
  typedef unsigned short           TUint16;
  typedef __int32                  TInt32;
  typedef unsigned __int32         TUint32;
  typedef __int64                  TInt64;
  typedef unsigned __int64         TUint64;
  typedef float                    TFloat;
  typedef double                   TDouble;

  typedef long                     TLong;
  typedef unsigned long            TUlong;
    
  #ifdef __cplusplus
    typedef bool                   TBool;
  #else
    typedef TInt8                  TBool;
  #endif

  typedef size_t                   TSize_t;
  typedef void                     TVoid;

  #ifdef _UNICODE
    typedef wchar_t                TXchar;
  #else
    typedef char                   TXchar;
  #endif

  // sizeof(TInt) in 32-bits system is 4 bytes, and in 64-bits is 8
  #ifdef _WIN64
    typedef long                   TInt;
    typedef unsigned long          TUint;
  #else
    typedef int                    TInt;
    typedef unsigned int           TUint;
  #endif

  // sizeof(TWint) is 8 bytes both in 32-bits and 64-bits system
  typedef __int64                  TWint;
  typedef unsigned __int64         TUwint;
    
#elif defined(__GNUC__)
  #if (__GNUC__ < 2) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
    #error "GCC compiler version too low, not support wchar_t."
  #endif
  
  typedef char                     TChar;
  typedef wchar_t                  TWchar;

  typedef char                     TInt8;
  typedef unsigned char            TUint8;
  typedef short                    TInt16;
  typedef unsigned short           TUint16;
  typedef int                      TInt32;
  typedef unsigned int             TUint32;
  typedef long long                TInt64;
  typedef unsigned long long       TUint64;
  typedef float                    TFloat;
  typedef double                   TDouble;

  typedef long                     TLong;
  typedef unsigned long            TUlong;

  typedef bool                     TBool;

  typedef size_t                   TSize_t;
  typedef void                     TVoid;

  #ifdef _UNICODE
    typedef wchar_t                TXchar;
  #else
    typedef char                   TXchar;
  #endif

  // sizeof(TInt) in 32-bits system is 4 bytes, and in 64-bits is 8
  #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
    typedef long                   TInt;
    typedef unsigned long          TUint;
  #else
    typedef int                    TInt;
    typedef unsigned int           TUint;
  #endif

  // sizeof(TWint) is 8 bytes both in 32-bits and 64-bits system
  typedef long long                TWint;
  typedef unsigned long long       TUwint;
#endif

typedef enum _UNUSED_ENUM {}       TEnumType;
typedef TVoid*                     TVoidp;
typedef TChar*                     TCharp;
typedef TWchar*                    TWcharp;
typedef TXchar*                    TXcharp;
typedef TInt32*                    TInt32p;
typedef TInt*                      TIntp;
typedef TLong*                     TLongp;

// size of TInt16, TInt32, TInt64 should correct
// otherwize, error will report at compile time
struct int_type_is_ok {int value: sizeof(TInt16)==2 && sizeof(TInt32)==4 && sizeof(TInt64)==8;};

// if sizeof(TInt) != sizeof(void *), error will report at compile time
// CSE system use TInt to hold symbol address also!
struct TInt_same_size_to {int a_pointer: sizeof(TInt) == sizeof(void *);};

// if sizeof(TInt) is not 4 or 8, error will report at compile time
// sizeof(TInt) == 4 is NORMAL_INT_SYS, 8 is LARGE_INT_SYS
struct TInt_must_be {int TInt32_or_TInt64: sizeof(TInt)==4 || sizeof(TInt)==8;};

#define CSE_INT_SIZE               sizeof(TInt)

#ifndef SIZE_T_MAX
  #define SIZE_T_MAX               ((size_t) -1)
#endif

#define CSE_CONCAT(text, post)     text ## post

#ifndef _T
  #if !CSE_USE_UNICODE
    #define _T(x)                  x
  #else
    #define _T(x)                  CSE_CONCAT(L,x)
  #endif
#endif

#ifndef _A
  #define _A(x)                    x
#endif

#ifndef _U
  #define _U(x)                    CSE_CONCAT(L,x)
#endif

#define CseFunc2C(f)               ((void*) &f)
#define PASS()

typedef struct
{
    const TXchar *ErrType;
    const TXchar *ErrDesc; 
    TInt32 ErrFlag;
} TAbsExcept;

#ifndef CSE_USE_PLATFORM
  #ifdef _DEBUG
    #define ASSERT_TRUE(cond)          assert(cond)
    #define ASSERT_MSG(cond,desc)      assert(cond)
  #else
    #define ASSERT_TRUE(cond)
    #define ASSERT_MSG(cond,desc)
  #endif

  #define WAIT_TO_DO()                 assert(0)

  #define CHECK_TRUE(cond)             assert(cond)
  #define CHECK_MSG(cond,desc)         assert(cond)
#endif

#define S_ATTR(obj,AClass,attr)        (((AClass *)&(obj))->attr)
#define S_PATTR(pObj,AClass,attr)      (((AClass *)pObj)->attr)
#define S_FUNC(obj,AClass,attr)        (((AClass *)&(obj))->func->attr)
#define S_PFUNC(pObj,AClass,attr)      (((AClass *)pObj)->func->attr)

#if defined(__cplusplus) && !defined(IN_EXTERNC_OF_CPP)
  template <class T> class TCObjHolder: public T
  { public:
    ~TCObjHolder() { this->func->free(this); }
  };
  #define OOC_TYPEDEF(T)  typedef TCObjHolder<class T##__> T
  #define OOC_TYPEDEF2(T) typedef TCObjHolder<struct T##__> T

  class IAbstract
  { public:
    IAbstract() { }
  };
  #define I_FUNC(obj,Func)             (((IAbstract *) &(obj))->*Func)
  #define I_PFUNC(pObj,Func)           (((IAbstract *) pObj)->*Func)
#else
  #define OOC_TYPEDEF(T)  typedef struct T##__ T
  #define OOC_TYPEDEF2(T) typedef struct T##__ T
#endif

#endif
